package filehandler

import (
	"bytes"
	"fmt"
	"frontmatter/internal/frontmatter"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"
)

type Frontmatter = frontmatter.Frontmatter

const frontmatterSeparator = frontmatter.SEPARATOR
const frontmatterSeparatorLength = frontmatter.SEPARATOR_LENGTH

func trimContentLeftNewline(content string) string {
	return strings.TrimLeft(strings.TrimLeft(content, "\n"), "\r\n")
}

// 处理单个文件，检查是否已有 Frontmatter，没有则添加，已有则补充缺失字段
func processFile(filePath string) error {
	// 读取文件内容
	fileContent, err := os.ReadFile(filePath)
	if err != nil {
		return fmt.Errorf("文件 %s 读取失败: %v", filePath, err)
	}

	content := string(fileContent)
	createtime, err := getFirstCommitTime(filePath)
	if err != nil {
		return err
	}

	updatetime, err := getLastCommitTime(filePath)
	if err != nil {
		return err
	}
	newFrontmatter := frontmatter.Create(filepath.Base(filePath), createtime, updatetime)
	var newContent string
	// 检查文件是否已有 Frontmatter（以 --- 开头）
	if !strings.HasPrefix(content, frontmatterSeparator) {
		// 序列化 Frontmatter 为 YAML 格式
		frontmatterYAML, err := frontmatter.ToString(newFrontmatter)
		if err != nil {
			return err
		}
		// 将新的 Frontmatter 添加到文件开头
		newContent = frontmatterYAML + trimContentLeftNewline(content)
	} else {
		oldFrontmatter, err := frontmatter.Parse(content)
		if err != nil {
			return fmt.Errorf("文件 %s 解析失败: %v", filePath, err)
		}
		// 检查是否缺少字段，如果有缺失则补充，注意，title必须是文件名称
		oldFrontmatter = frontmatter.Fill(oldFrontmatter, newFrontmatter)
		// 如果有更新，重新生成 Frontmatter 并保存文件
		frontmatterYAML, err := frontmatter.ToString(oldFrontmatter)
		if err != nil {
			return err
		}
		endIndex := oldFrontmatter.SecondIndex
		newContent = frontmatterYAML + trimContentLeftNewline(content[endIndex+frontmatterSeparatorLength:])
	}
	// 将更新后的内容写回文件
	err = os.WriteFile(filePath, []byte(newContent), 0644)
	if err != nil {
		return fmt.Errorf("写入内容到文件 %s 失败: %v", filePath, err)
	}

	return nil
}

// 遍历目录，处理所有 .md 文件
func ProcessDirectory(dirPath string) error {
	return filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		// 只处理 .md 文件
		if !info.IsDir() && strings.HasSuffix(info.Name(), ".md") {
			return processFile(path)
		}
		return nil
	})
}

func formatDate(date time.Time) string {
	return strings.TrimSpace(fmt.Sprintf("%d-%02d-%02d %02d:%02d:%02d",
	date.Year(), date.Month(), date.Day(),
	date.Hour(), date.Minute(), date.Second()))
}

func getFirstCommitTime(filePath string) (string, error) {
	// 执行 git log 命令，获取首次提交时间
	cmd := exec.Command("git", "log", "--diff-filter=A", "--reverse", "--date=iso", "--format=%cd", filePath)
	var out bytes.Buffer
	cmd.Stdout = &out

	// 执行命令
	err := cmd.Run()
	if err != nil {
		return "", fmt.Errorf("获取首次提交时间失败: %w", err)
	}

	commitDateStr := strings.TrimSpace(out.String()) // 使用 strings.TrimSpace 去除前后空白和换行符
	// 解析 Git 输出的 ISO 8601 日期字符串
	commitDate, err := time.Parse("2006-01-02 15:04:05 -0700", commitDateStr)
	if err != nil {
		fmt.Println(commitDate)
		return "", fmt.Errorf("解析提交日期失败: %w", err)
	}

	// 将日期格式化为中文日期格式
	return formatDate(commitDate), nil
}

// 获取文件的最后一次提交时间
func getLastCommitTime(filePath string) (string, error) {
	// 执行 git log 命令，获取最后一次提交时间
	cmd := exec.Command("git", "log", "-1", "--date=iso", "--format=%cd", filePath)
	var out bytes.Buffer
	cmd.Stdout = &out

	// 执行命令
	err := cmd.Run()
	if err != nil {
		return "", fmt.Errorf("获取最后一次提交时间失败: %w", err)
	}

	commitDateStr := strings.TrimSpace(out.String()) // 使用 strings.TrimSpace 去除前后空白和换行符
	// 解析 Git 输出的 ISO 8601 日期字符串
	commitDate, err := time.Parse("2006-01-02 15:04:05 -0700", commitDateStr)
	if err != nil {
		return "", fmt.Errorf("解析提交日期失败: %w", err)
	}

	// 将日期格式化为中文日期格式
	return formatDate(commitDate), nil
}
